home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 301-325 / 325 / keymacro / keymacro-handler.c < prev    next >
C/C++ Source or Header  |  1995-03-14  |  11KB  |  595 lines

  1. #include "KeyMacro.h"
  2.  
  3. struct MXMBase        *MXMBase;
  4. struct IntuitionBase    *IntuitionBase;
  5.  
  6. struct MSeg        *MSeg;
  7. LONG             MSignal = -1;
  8. struct KeyEquivalent    *EquList;
  9.  
  10. struct Process        *ExecuteProc;
  11. struct MsgPort        *ExecutePort;
  12.  
  13. struct MsgPort        *InputDevPort;
  14. struct IOStdReq        *InputRequestBlock;
  15. struct Interrupt     HandlerStuff;
  16.  
  17. long             ConsoleDevice = NULL;
  18. struct IOStdReq         ConStdReq;
  19.  
  20.     /* FreeString(Byte):
  21.      *
  22.      *    Frees the memory occupied by the contents of a BSTR.
  23.      */
  24.  
  25. void
  26. FreeString(Byte)
  27. BPTR Byte;
  28. {
  29.     long *Ptr = (long *)BADDR(Byte);
  30.  
  31.     FreeMem(Ptr - 1,Ptr[-1]);
  32. }
  33.  
  34.     /* CreateBSTR(s):
  35.      *
  36.      *    Allocates enough memory to hold the contents of
  37.      *    a given string and makes it a BSTR.
  38.      */
  39.  
  40. BPTR
  41. CreateBSTR(s)
  42. char *s;
  43. {
  44.     long Length = strlen(s);
  45.     long BlockLength = (Length + 8) & ~3;
  46.     char *Byte;
  47.  
  48.     if(!(Byte = (char *)AllocMem(BlockLength,MEMF_PUBLIC | MEMF_CLEAR)))
  49.         return(NULL);
  50.  
  51.     *(long *)Byte = BlockLength;
  52.  
  53.     Byte[4] = Length;
  54.     strncpy(Byte + 5,s,Length);
  55.  
  56.     return((long)(Byte + 4) >> 2);
  57. }
  58.  
  59.     /* CopyPath():
  60.      *
  61.      *    Builds a fake pathlist inherited from any valid
  62.      *    CLI process or Workbench.
  63.      */
  64.  
  65. BPTR
  66. CopyPath()
  67. {
  68.     struct Process *Father;
  69.     struct CommandLineInterface *CLI;
  70.     BPTR *Next1,*Next2,*Last,NewPath = NULL;
  71.  
  72.     Last = &NewPath;
  73.  
  74.         /* If using ARP this will also give us a valid
  75.          * pathlist.
  76.          */
  77.  
  78.     if(!(Father = (struct Process *)FindTask("Workbench")))
  79.         if(!(Father = (struct Process *)FindTask("ARP Shell Process")))
  80.             if(!(Father = (struct Process *)FindTask("New CLI")))
  81.                 if(!(Father = (struct Process *)FindTask("Initial CLI")))
  82.                     return(NULL);
  83.  
  84.     if(!(CLI = (struct CommandLineInterface *)BADDR(Father -> pr_CLI)))
  85.         return(NULL);
  86.  
  87.     for(Next1 = (BPTR *)BADDR(CLI -> cli_CommandDir) ; Next1 ; Next1 = (BPTR *)BADDR(*Next1))
  88.     {
  89.         if(!(Next2 = (BPTR *)AllocMem(2 * sizeof(BPTR),MEMF_PUBLIC | MEMF_CLEAR)))
  90.             break;
  91.  
  92.         *Last = (long)Next2 >> 2;
  93.         Last = Next2;
  94.  
  95.         Next2[1] = (BPTR)DupLock(Next1[1]);
  96.         Next2[0] = NULL;
  97.     }
  98.  
  99.     return(NewPath);
  100. }
  101.  
  102.     /* FakeCLI():
  103.      *
  104.      *    Creates a fake CLI structure for out process. This
  105.      *    includes pathlist, currentdir, prompt and stack.
  106.      */
  107.  
  108. void
  109. FakeCLI()
  110. {
  111.     struct CommandLineInterface *CLI;
  112.     struct Process *MyProcess = (struct Process *)FindTask(NULL);
  113.  
  114.     if(!(CLI = (struct CommandLineInterface *)AllocMem(sizeof(struct CommandLineInterface),MEMF_PUBLIC | MEMF_CLEAR)))
  115.         return;
  116.  
  117.     MyProcess -> pr_CLI = (long)CLI >> 2;
  118.  
  119.     CLI -> cli_SetName    = CreateBSTR("SYS:");
  120.     CLI -> cli_Prompt    = CreateBSTR("%N> ");
  121.     CLI -> cli_DefaultStack    = 4000;
  122.  
  123.     CurrentDir(Lock("SYS:",ACCESS_READ));
  124.  
  125.     CLI -> cli_CommandDir    = CopyPath();
  126. }
  127.  
  128.     /* ClearPath(InitPath):
  129.      *
  130.      *    Frees the contents of our fake pathlist.
  131.      */
  132.  
  133. void
  134. ClearPath(InitPath)
  135. BPTR InitPath;
  136. {
  137.     BPTR *Next,*Path;
  138.  
  139.     for(Path = (BPTR *)BADDR(InitPath) ; Path ; Path = Next)
  140.     {
  141.         Next = (BPTR *)BADDR(Path[0]);
  142.  
  143.         if(Path[1])
  144.             UnLock(Path[1]);
  145.  
  146.         FreeMem(Path,2 * sizeof(BPTR));
  147.     }
  148. }
  149.  
  150.     /* StopFakery():
  151.      *
  152.      *    Removes the contents of our fake CLI structure.
  153.      */
  154.  
  155. void
  156. StopFakery()
  157. {
  158.     BPTR MyCD = (BPTR)CurrentDir(NULL);
  159.     struct Process *MyProcess = (struct Process *)FindTask(NULL);
  160.     struct CommandLineInterface *CLI = (struct CommandLineInterface *)BADDR(MyProcess -> pr_CLI);
  161.  
  162.     if(!CLI)
  163.         return;
  164.  
  165.     if(MyCD)
  166.         UnLock(MyCD);
  167.  
  168.     FreeString(CLI -> cli_SetName);
  169.     FreeString(CLI -> cli_Prompt);
  170.  
  171.     ClearPath(CLI -> cli_CommandDir);
  172.  
  173.     MyProcess -> pr_CLI = NULL;
  174.  
  175.     FreeMem(CLI,sizeof(struct CommandLineInterface));
  176. }
  177.  
  178. void *
  179. DeleteCustomMsg(scm_Msg)
  180. struct MacroMessage *scm_Msg;
  181. {
  182.     if(scm_Msg && scm_Msg -> mm_Message . mn_Node . ln_Name == scm_Msg)
  183.         FreeRem(scm_Msg);
  184.  
  185.     return(NULL);
  186. }
  187.  
  188. void *
  189. SendCustomMsg(scm_Msg,scm_Port)
  190. struct MacroMessage *scm_Msg;
  191. struct MsgPort *scm_Port;
  192. {
  193.     struct MacroMessage *scm_TempMsg = (struct MacroMessage *)AllocRem(sizeof(struct MacroMessage),MEMF_PUBLIC | MEMF_CLEAR);
  194.  
  195.     if(scm_TempMsg)
  196.     {
  197.         CopyMem(scm_Msg,scm_TempMsg,sizeof(struct MacroMessage));
  198.  
  199.         scm_TempMsg -> mm_Message . mn_Node . ln_Name    = (char *)scm_TempMsg;
  200.         scm_TempMsg -> mm_Message . mn_ReplyPort    = NULL;
  201.         scm_TempMsg -> mm_Message . mn_Length        = sizeof(struct MacroMessage);
  202.  
  203.         PutMsg(scm_Port,scm_TempMsg);
  204.     }
  205.  
  206.     return((void *)scm_TempMsg);
  207. }
  208.  
  209. void
  210. Executor()
  211. {
  212.     ULONG SignalSet,NilHandle;
  213.     struct MacroMessage *ExecuteMsg;
  214.     struct Window *TheWindow;
  215.  
  216.     geta4();
  217.  
  218.     if(!(ExecutePort = (struct MsgPort *)CreatePort(NULL,0)))
  219.         return;
  220.  
  221.     if(!(NilHandle = (ULONG)Open("NIL:",MODE_NEWFILE)))
  222.     {
  223.         DeletePort(ExecutePort);
  224.         return;
  225.     }
  226.  
  227.     FakeCLI();
  228.  
  229.     FOREVER
  230.     {
  231.         SignalSet = Wait(SIG_CLOSE | (1 << ExecutePort -> mp_SigBit));
  232.  
  233.         if(SignalSet & SIG_CLOSE)
  234.         {
  235.             StopFakery();
  236.             Close(NilHandle);
  237.             DeletePort(ExecutePort);
  238.  
  239.             ExecuteProc = NULL;
  240.  
  241.             return;
  242.         }
  243.  
  244.         while(ExecuteMsg = (struct MacroMessage *)GetMsg(ExecutePort))
  245.         {
  246.             TheWindow = NULL;
  247.  
  248.             if(ExecuteMsg -> mm_WindowName)
  249.             {
  250.                 ULONG IntuiLock;
  251.  
  252.                 struct Screen *ExScreen;
  253.                 struct Window *ExWindow;
  254.  
  255.                 IntuiLock = LockIBase(NULL);
  256.  
  257.                 ExScreen = IntuitionBase -> FirstScreen;
  258.  
  259.                 do
  260.                 {
  261.                     ExWindow = ExScreen -> FirstWindow;
  262.  
  263.                     do
  264.                     {
  265.                         if(!UStrCmp(ExecuteMsg -> mm_WindowName,ExWindow -> Title))
  266.                         {
  267.                             UnlockIBase(IntuiLock);
  268.  
  269.                             TheWindow = ExWindow;
  270.  
  271.                             goto SkipLoop;
  272.                         }
  273.                     }
  274.                     while(ExWindow = ExWindow -> NextWindow);
  275.                 }
  276.                 while(ExScreen = ExScreen -> NextScreen);
  277.  
  278.                 UnlockIBase(IntuiLock);
  279.             }
  280.  
  281.             Execute(ExecuteMsg -> mm_FileName,NULL,NilHandle);
  282.  
  283. SkipLoop:        DeleteCustomMsg(ExecuteMsg);
  284.  
  285.             if(TheWindow)
  286.             {
  287.                 WindowToFront(TheWindow);
  288.                 ScreenToFront(TheWindow -> WScreen);
  289.                 ActivateWindow(TheWindow);
  290.             }
  291.         }
  292.     }
  293. }
  294.  
  295. struct MacroKey *
  296. FindMacroKey(Code,Qualifier)
  297. LONG Code,Qualifier;
  298. {
  299.     long i;
  300.  
  301.     if(!MSeg -> MacroList)
  302.         return(NULL);
  303.  
  304.     for(i = 0 ; i < MSeg -> NumMacros ; i++)
  305.     {
  306.         if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
  307.             continue;
  308.  
  309.         if(MSeg -> MacroList[i] . mk_CommandKey == Code && (Qualifier & MSeg -> MacroList[i] . mk_CommandQualifier) == MSeg -> MacroList[i] . mk_CommandQualifier)
  310.             return(&MSeg -> MacroList[i]);
  311.     }
  312.  
  313.     return(NULL);
  314. }
  315.  
  316. #asm
  317. _Handler:    MOVEM.L    A4,-(A7)
  318.         MOVEM.L    A0/A1,-(A7)
  319.  
  320.         JSR    _geta4#
  321.         JSR    _EventHandler
  322.  
  323.         ADDQ.L    #8,A7
  324.  
  325.         MOVEM.L    (A7)+,A4
  326.  
  327.         RTS
  328. #endasm
  329.  
  330. struct InputEvent *
  331. EventHandler(Event)
  332. struct InputEvent *Event;
  333. {
  334.     register struct MacroKey *HandlerKey;
  335.  
  336.     if(Event -> ie_Class != IECLASS_RAWKEY || Event -> ie_Code & IECODE_UP_PREFIX)
  337.         return(Event);
  338.  
  339.     if(HandlerKey = (struct MacroKey *)FindMacroKey(Event -> ie_Code,Event -> ie_Qualifier))
  340.     {
  341.         struct MacroMessage HandlerMsg;
  342.  
  343.         HandlerMsg . mm_Type    = MM_INPUT;
  344.         HandlerMsg . mm_MacroKey= HandlerKey;
  345.  
  346.         SendCustomMsg(&HandlerMsg,&MSeg -> Port);
  347.  
  348.         Event -> ie_Class = IECLASS_NULL;
  349.     }
  350.  
  351.     return(Event);
  352. }
  353.  
  354. BOOL
  355. InitHandler()
  356. {
  357.     extern void Handler();
  358.  
  359.     if(OpenDevice("console.device",-1,&ConStdReq,0))
  360.         return(FALSE);
  361.  
  362.     ConsoleDevice = (long)ConStdReq . io_Device;
  363.  
  364.     if(!(InputDevPort = (struct MsgPort *)CreatePort(NULL,0)))
  365.         return(FALSE);
  366.  
  367.     if(!(InputRequestBlock = (struct IOStdReq *)CreateStdIO(InputDevPort)))
  368.         return(FALSE);
  369.  
  370.     if(OpenDevice("input.device",0,InputRequestBlock,0))
  371.         return(FALSE);
  372.  
  373.     HandlerStuff . is_Code        = Handler;
  374.     HandlerStuff . is_Node . ln_Pri    = 60;
  375.     HandlerStuff . is_Node . ln_Name= "KeyMacro-Handler";
  376.  
  377.     InputRequestBlock -> io_Command    = IND_ADDHANDLER;
  378.     InputRequestBlock -> io_Data    = (APTR)&HandlerStuff;
  379.  
  380.     DoIO(InputRequestBlock);
  381.  
  382.     return(TRUE);
  383. }
  384.  
  385. void
  386. FlushHandler()
  387. {
  388.     if(ConsoleDevice)
  389.         CloseDevice(&ConStdReq);
  390.  
  391.     if(InputRequestBlock -> io_Device)
  392.     {
  393.         InputRequestBlock -> io_Command    = IND_REMHANDLER;
  394.         InputRequestBlock -> io_Data    = (APTR)&HandlerStuff;
  395.  
  396.         DoIO(InputRequestBlock);
  397.  
  398.         CloseDevice(InputRequestBlock);
  399.     }
  400.  
  401.     if(InputRequestBlock)
  402.         DeleteStdIO(InputRequestBlock);
  403.  
  404.     if(InputDevPort)
  405.         DeletePort(InputDevPort);
  406. }
  407.  
  408. void
  409. ShutDown()
  410. {
  411.     FlushHandler();
  412.  
  413.     if(ExecuteProc)
  414.     {
  415.         Signal(ExecuteProc,SIG_CLOSE);
  416.  
  417.         while(ExecuteProc)
  418.             Delay(10);
  419.     }
  420.  
  421.     if(MXMBase)
  422.         CloseLibrary(MXMBase);
  423.  
  424.     if(MSignal != -1)
  425.         FreeSignal(MSignal);
  426.  
  427.     Forbid();
  428.  
  429.     if(MSeg -> Father)
  430.         Signal(MSeg -> Father,SIG_CLOSE);
  431.  
  432.     if(!MSeg -> Father)
  433.     {
  434.         register BPTR Segment = MSeg -> Segment;
  435.  
  436.         RemPort(&MSeg -> Port);
  437.         FreeMem(MSeg -> Port . mp_Node . ln_Name,sizeof(PORTNAME));
  438.  
  439.         UnLoadSeg(Segment);
  440.  
  441.         Wait(NULL);
  442.     }
  443. }
  444.  
  445. long
  446. _main()
  447. {
  448.     struct Process *ThatsMe = (struct Process *)FindTask(NULL);
  449.     ULONG SignalSet;
  450.  
  451.     struct MacroMessage *MacroMsg;
  452.  
  453.     register long i;
  454.  
  455.     if(ThatsMe -> pr_CLI)
  456.         return(10);
  457.  
  458.     if(!(MSeg = (struct MSeg *)FindPort(PORTNAME)))
  459.         return(10);
  460.  
  461.     if(MSeg -> Port . mp_Flags == PA_SIGNAL)
  462.         return(10);
  463.  
  464.     if(MSeg -> Revision < REVISION)
  465.     {
  466.         Signal(MSeg -> Father,MSeg -> RingBack);
  467.  
  468.         return(10);
  469.     }
  470.  
  471.     if(!InitHandler())
  472.     {
  473.         FlushHandler();
  474.         Signal(MSeg -> Father,MSeg -> RingBack);
  475.  
  476.         return(20);
  477.     }
  478.  
  479.     if(!(MXMBase = (struct MXMBase *)OpenLibrary("mxm.library",0)))
  480.     {
  481.         FlushHandler();
  482.         Signal(MSeg -> Father,MSeg -> RingBack);
  483.  
  484.         return(20);
  485.     }
  486.  
  487.     IntuitionBase = (struct IntuitionBase *)MXMBase -> IntuitionBase;
  488.  
  489.     if((MSignal = AllocSignal(-1)) == -1)
  490.     {
  491.         CloseLibrary(MXMBase);
  492.         FlushHandler();
  493.         Signal(MSeg -> Father,MSeg -> RingBack);
  494.  
  495.         return(20);
  496.     }
  497.  
  498.     if(!(ExecuteProc = (struct Process *)CreateFuncProc("KeyMacro.exec",10,Executor,4000)))
  499.     {
  500.         FreeSignal(MSignal);
  501.         CloseLibrary(MXMBase);
  502.         FlushHandler();
  503.         Signal(MSeg -> Father,MSeg -> RingBack);
  504.  
  505.         return(20);
  506.     }
  507.  
  508.     MSeg -> Child = (struct Task *)ThatsMe;
  509.  
  510.     Signal(MSeg -> Father,MSeg -> RingBack);
  511.  
  512.     MSeg -> Father = NULL;
  513.  
  514.     MSeg -> Port . mp_Flags        = PA_SIGNAL;
  515.     MSeg -> Port . mp_SigBit    = MSignal;
  516.     MSeg -> Port . mp_SigTask    = MSeg -> Child;
  517.  
  518.     FOREVER
  519.     {
  520.         SignalSet = Wait(SIG_CLOSE | SIG_PORT);
  521.  
  522.         if(SignalSet & SIG_CLOSE)
  523.         {
  524.             ShutDown();
  525.             return(0);
  526.         }
  527.  
  528.         if(SignalSet & SIG_PORT)
  529.         {
  530.             while(MacroMsg = (struct MacroMessage *)GetMsg(&MSeg -> Port))
  531.             {
  532.                 if(MacroMsg -> mm_Type == MM_INPUT)
  533.                 {
  534.                     struct MacroKey *TempMacroKey = MacroMsg -> mm_MacroKey;
  535.  
  536.                     if(TempMacroKey)
  537.                     {
  538.                         if(TempMacroKey -> mk_Type == MK_COMMAND)
  539.                         {
  540.                             struct MacroMessage CommandMsg;
  541.  
  542.                             CommandMsg . mm_Type        = MM_EXECUTE;
  543.                             CommandMsg . mm_FileName    = TempMacroKey -> mk_String;
  544.                             CommandMsg . mm_WindowName    = TempMacroKey -> mk_Window;
  545.  
  546.                             SendCustomMsg(&CommandMsg,ExecutePort);
  547.                         }
  548.  
  549.                         if(TempMacroKey -> mk_Type == MK_WORD)
  550.                         {
  551.                             struct InputEvent FakeInputEvent;
  552.  
  553.                             InputRequestBlock -> io_Command    = IND_WRITEEVENT;
  554.                             InputRequestBlock -> io_Data    = (APTR)&FakeInputEvent;
  555.  
  556.                             setmem(&FakeInputEvent,sizeof(struct InputEvent),0);
  557.  
  558.                             FakeInputEvent . ie_Class = IECLASS_RAWKEY;
  559.  
  560.                             for(i = 0 ; i < strlen(TempMacroKey -> mk_String) ; i++)
  561.                                 if(InvertKey(TempMacroKey -> mk_String[i],&FakeInputEvent,IK_USEIKM,NULL))
  562.                                     DoIO(InputRequestBlock);
  563.                         }
  564.                     }
  565.                 }
  566.  
  567.                 if(MacroMsg -> mm_Type == MM_UPDATE)
  568.                 {
  569.                     if(MSeg -> MacroList)
  570.                     {
  571.                         for(i = 0 ; i < MSeg -> NumMacros ; i++)
  572.                         {
  573.                             if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
  574.                                 continue;
  575.  
  576.                             if(MSeg -> MacroList[i] . mk_String)
  577.                                 FreeRem(MSeg -> MacroList[i] . mk_String);
  578.  
  579.                             if(MSeg -> MacroList[i] . mk_Window)
  580.                                 FreeRem(MSeg -> MacroList[i] . mk_Window);
  581.                         }
  582.  
  583.                         FreeRem(MSeg -> MacroList);
  584.                     }
  585.  
  586.                     MSeg -> NumMacros = MacroMsg -> mm_NumMacros;
  587.                     MSeg -> MacroList = MacroMsg -> mm_MacroList;
  588.                 }
  589.  
  590.                 DeleteCustomMsg(MacroMsg);
  591.             }
  592.         }
  593.     }
  594. }
  595.